﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CrankShaftAnalysisSystem.Devices;

namespace CrankShaftAnalysisSystem
{
    public class PLCMaster // 单例模式
    {
        private static readonly PLCMaster instance = new PLCMaster();

        /// <summary>
        /// 显式的静态构造函数用来告诉C#编译器在其内容实例化之前不要标记其类型
        /// 静态构造函数是C#的一个新特性，其实好像很少用到。 
        /// 不过当我们想初始化一些静态变量的时候就需要用到它了。 这个构造函数是属于类的，
        /// 而不是属于哪里实例的，就是说这个构造函数只会被执行一次。 
        /// 也就是在创建第一个实例或引用任何静态成员之前，由.NET自动调用
        /// </summary>
        static PLCMaster() { }

        private PLCMaster() {
            Device = new VirtualDevice("192.168.3.10", 502);
        }

        public static PLCMaster Instance
        {
            get
            {
                return instance;
            }
        }

        public const int MotorMaxVel = 2000;

        [Description("PLC设备")]
        public VirtualDevice Device;

        [Description("气缸缩回零件可以取和放")]
        public bool PartCanBePlaced { get { 
                return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS0);
            } }

        [Description("激光传感器得到数据，零件放置位置OK")]
        public bool PartPlaceOk { get {
                return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.PARTEXIST);
            } }

        [Description("急停被按下")]
        public bool Emergency { get
            {
                return !Tools.GetBitState(Device.Info.SafeInfo, VirtualDevice.Mask.EMERGENCY);
            } }

        [Description("零件被夹紧")]
        public bool PartFastened { get
            {
                return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS1);
            } }

        [Description("探头已经伸出")]
        public bool MT2571IsOut { get { 
                return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS2);
            } }

        [Description("探头缩回")]
        public bool MT2571IsBack { get { 
                return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS3); 
            } }

        [Description("自动启动灯常亮")]
        public bool AutoRunLedOn
        {
            get { return Tools.GetBitState(Device.Info.FeedBackInfo, VirtualDevice.Mask.AUTOLED); }
        }

        /// <summary>
        /// 设置速度
        /// </summary>
        /// <param name="axis">轴编号1,2,3</param>
        /// <param name="vel">速度值</param>
        public void SetSpeed(int axis, int vel)
        {
            // 限制速度
            if (Math.Abs(vel) > MotorMaxVel)
                vel = Math.Sign(vel) * MotorMaxVel;

            ushort[] address = new ushort[3] {
                VirtualDevice.Address.Axis1Speed,
                VirtualDevice.Address.Axis2Speed,
                VirtualDevice.Address.Axis3Speed
            };
            if(vel<0 && axis ==3)
            {
                if (DistanceEastenGauge.Instance.PenCompressionReached())
                {
                    vel = 0;
                    Console.WriteLine("Can't Move More, Pen Compression Reached");
                }
            }
            ushort[] registers = new ushort[2] { Tools.LowWord((uint)vel), Tools.HighWord((uint)vel) };
            try
            {
                var msg = new ModbusProxy.Message();
                msg.Address = address[axis - 1];
                msg.Regs = registers;
                Device.SendRegisters(msg);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[Motor Error]: {ex.Message}");
            }
        }
    }
}
